<template>
  <div class="text-expansion-container">
    <!-- 顶部输入区域 -->
    <div class="input-section">
      <div class="input-container">
        <div class="input-wrapper">
          <a-textarea
            v-model:value="inputText"
            placeholder="输入您的文本，AI将为您扩展内容并生成专业的思维导图"
            :rows="4"
            :maxlength="3000"
            show-count
            class="text-input"
          />
        </div>
        <div class="action-buttons">
          <a-button
            type="primary"
            size="large"
            :loading="isGenerating "
            @click="generateText"
            :disabled="!inputText.trim() || isGenerating"
            class="send-button"
          >
            <template #icon>
              <SendOutlined />
            </template>
            {{ isGenerating ? '正在生成...' : '发送' }}
          </a-button>
        </div>
      </div>
    </div>
    <!-- 主要内容区域 -->
    <div class="content-section">
      <div class="content-layout">
        <!-- 左侧 Markdown 编辑器 -->
        <div class="markdown-panel">
          <div class="panel-header">
            <h3>Markdown</h3>
            <div class="panel-actions">
              <a-tooltip title="下载MD文件">
                <a-button
                  type="text"
                  size="small"
                  @click="downloadMarkdown"
                  :disabled="!markdownContent"
                >
                  <template #icon>
                    <DownloadOutlined />
                  </template>
                </a-button>
              </a-tooltip>
            </div>
          </div>

          <div class="markdown-editor-container">
            <codemirror
              v-model="markdownContent"
              placeholder="生成的Markdown内容将显示在这里..."
              :style="{ height: '100%' }"
              :autofocus="false"
              :indent-with-tab="true"
              :tab-size="2"
              :extensions="extensions"
              class="markdown-editor"
            />
          </div>
        </div>

        <!-- 右侧思维导图 -->
        <div class="mindmap-panel">
          <div class="panel-header">
            <h3>思维导图</h3>
            <div class="panel-actions">
              <a-tooltip title="适应视图">
                <a-button type="text" size="small" @click="fitView" :disabled="!markdownContent">
                  <template #icon>
                    <ExpandOutlined />
                  </template>
                </a-button>
              </a-tooltip>

              <a-tooltip title="导出SVG">
                <a-button type="text" size="small" @click="exportSVG" :disabled="!markdownContent">
                  <template #icon>
                    <PictureOutlined />
                  </template>
                </a-button>
              </a-tooltip>

              <a-tooltip title="导出PNG">
                <a-button type="text" size="small" @click="exportPNG" :disabled="!markdownContent">
                  <template #icon>
                    <PictureOutlined />
                  </template>
                </a-button>
              </a-tooltip>
            </div>
          </div>

          <div class="mindmap-wrapper">
            <svg class="mindmap-container" ref="svgRef"></svg>
            <div class="mindmap-controls"></div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { ref, onMounted, nextTick, onUnmounted, watch } from 'vue'
import { message } from 'ant-design-vue'
import {
  SendOutlined,
  DownloadOutlined,
  PictureOutlined,
  ExpandOutlined,
} from '@ant-design/icons-vue'
import { Codemirror } from 'vue-codemirror'
import { markdown } from '@codemirror/lang-markdown'
import { Markmap } from 'markmap-view'
import { Transformer } from 'markmap-lib'
import request from '@/request'
import { API_BASE_URL } from '@/config/env'

// 初始示例内容
const initValue = `# MindMap 思维导图

## 主要特点
- **美观**：现代化的视觉设计
- **实用**：支持完整的Markdown语法
- **简单**：易于使用和理解
- **交互**：支持拖拽、缩放、折叠

## 功能特性
- 实时预览
- 导出功能
- 响应式设计

## 使用方法
1. 编辑左侧Markdown内容
2. 右侧自动生成思维导图
3. 支持导出SVG和PNG格式`

// 响应式数据
const inputText = ref('')
const markdownContent = ref(initValue)
const isGenerating = ref(false)
const svgRef = ref<SVGElement>()

// CodeMirror 配置
const extensions = [markdown()]

// Markmap 实例
let mm: Markmap | null = null
const transformer = new Transformer()

// 自动滚动到编辑器底部
const scrollToBottom = () => {
  nextTick(() => {
    const editorElement = document.querySelector('.cm-editor .cm-scroller')
    if (editorElement) {
      editorElement.scrollTop = editorElement.scrollHeight
    }
  })
}
// TensorFlow.js详解大纲内容
const tensorflowContent = `# TensorFlow.js详解


## TensorFlow.js概述

### 定义与核心功能
- TensorFlow.js是TensorFlow的JavaScript版本，可在浏览器和Node.js环境运行。
- 支持GPU加速，提升模型训练和推理效率。
- 允许使用JavaScript开发、训练和部署机器学习模型。
- 可导入和转换已有的TensorFlow模型。

### 运行环境
- 浏览器环境：利用WebGL进行GPU加速，实现高效计算。
- Node.js环境：在服务器端进行模型训练和部署。


## TensorFlow.js优势

### 开发便捷性
- 开箱即用：提供简洁易用的API，降低开发门槛。
- JavaScript支持：前端开发者可以直接使用，无需学习其他语言。

### 性能与效率
- GPU加速：利用浏览器或Node.js环境的GPU资源，显著提升性能。
- 高性能计算：在Node.js环境下，性能与Python版本接近。

### 应用场景与灵活性
- 浏览器运行：减少服务器负载，提高响应速度，适合Web应用。
- 移动端和IOT设备支持：拓展应用范围，实现边缘计算。
- 模型互转：方便与其他平台的TensorFlow模型进行交互。
- 可视化与交互性：增强用户体验，方便调试和监控。


## TensorFlow.js应用案例

### Web应用中的机器学习
- 实时图像识别：利用浏览器摄像头进行图像分类或目标检测。
- 自然语言处理：构建网页上的聊天机器人或文本分析工具。
- 个性化推荐：根据用户行为进行个性化推荐。

### 移动端与IOT应用
- 物联网设备上的模型部署：在资源受限的设备上运行机器学习模型。
- 移动应用中的机器学习：提升移动应用的智能化程度。

### 其他应用场景
- 数据可视化：利用TensorFlow.js进行数据分析和可视化。
- 游戏开发：在游戏中应用机器学习技术，例如AI对手。


## TensorFlow.js的局限性

###  浏览器兼容性
-  并非所有浏览器都完全支持WebGL或其他必要的特性。

###  模型大小限制
-  浏览器环境对模型大小可能存在限制。

###  调试难度
-  相较于Python环境，JavaScript的调试可能更具挑战性。


## TensorFlow.js未来发展

###  性能优化
-  持续改进GPU加速性能，提升模型训练和推理速度。

###  API改进
-  改进API设计，使其更易于使用和理解。

###  生态系统扩展
-  增加更多预训练模型和工具，拓展应用范围。`
// 文本扩展API调用
const generateText = async ()=> {
  let eventSource: EventSource | null = null
  let streamCompleted = false

  try {
    // 获取 axios 配置的 baseURL
    const baseURL = request.defaults.baseURL || API_BASE_URL

    // 构建URL参数
    const params = new URLSearchParams({
      prompt: inputText.value,
    })

    const url = `${baseURL}/multi_modal/gen/mind_map/stream?${params}`

    // 创建 EventSource 连接
    eventSource = new EventSource(url, {
      withCredentials: true,
    })

    let fullContent = ''
    markdownContent.value = ''
    // 处理接收到的消息
    eventSource.onmessage = function(event) {
      if (streamCompleted) return

      try {
        // 解析JSON包装的数据
        const parsed = JSON.parse(event.data)
        const content = parsed.d

        // 拼接内容
        if (content !== undefined && content !== null) {
          fullContent += content
          console.log(content)
          markdownContent.value = fullContent
          // 自动滚动到底部
          scrollToBottom()
        }
      } catch (error) {
        console.error('解析消息失败:', error)
        handleError(error)
      }

      // 处理done事件
      eventSource.addEventListener('done', function() {
        if (streamCompleted) return

        streamCompleted = true
        isGenerating.value = false
        eventSource?.close()
      })
      // 处理错误
      eventSource.onerror = function() {
        if (streamCompleted || !isGenerating.value) return
        // 检查是否是正常的连接关闭
        if (eventSource?.readyState === EventSource.CONNECTING) {
          streamCompleted = true
          isGenerating.value = false
          eventSource?.close()

        } else {
          handleError(new Error('SSE连接错误'))
        }
      }
    }
  } catch(error)
    {
      console.error('创建 EventSource 失败：', error)
      handleError(error)
    }
  }

// 错误处理函数
  const handleError = (error: unknown) => {
    console.error('生成代码失败：', error)
    message.error('生成失败，请重试')
    isGenerating.value = false
  }
// 模拟AI文本扩展API调用
  const generateContent = async () => {
    if (!inputText.value.trim()) {
      message.warning('请输入文本内容')
      return
    }

    isGenerating.value = true

    try {
      // 模拟API调用延迟
      await new Promise((resolve) => setTimeout(resolve, 1000))

      // 使用打字机效果展示TensorFlow.js详解大纲
      await typewriterEffect(tensorflowContent, 0.9)

      message.success('内容生成成功！')
    } catch (error) {
      message.error('生成失败，请重试')
      console.error('Generate content error:', error)
    } finally {
      isGenerating.value = false
    }
  }
// 更新思维导图 - 参考示例的简洁实现
  const update = async () => {
    // console.log('Update called, markdownContent:', markdownContent.value, 'mm:', mm)
    if (!markdownContent.value || !mm) {
      return
    }

    try {
      const { root } = transformer.transform(markdownContent.value)
      await mm.setData(root)
      await mm.fit()
    } catch (error) {
      message.error('思维导图更新失败')
    }
  }

// 监听Markdown内容变化，自动更新思维导图 - 参考示例的onUpdated
  watch(markdownContent, update)
// 适应视图
  const fitView = () => {
    if (mm) {
      mm.fit(0.8)
      // mm.rescale()
      message.success('视图已适应')
    }
  }

// 导出SVG
  const exportSVG = () => {
    if (!mm || !svgRef.value) {
      message.warning('暂无思维导图可导出')
      return
    }

    try {
      // 克隆SVG并设置样式
      const svgClone = svgRef.value.cloneNode(true) as SVGElement
      svgClone.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
      svgClone.style.background = '#ffffff'

      // 获取SVG字符串
      const svgData = new XMLSerializer().serializeToString(svgClone)
      const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' })
      const url = URL.createObjectURL(blob)

      // 下载文件
      const a = document.createElement('a')
      a.href = url
      a.download = `mindmap-${Date.now()}.svg`
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      URL.revokeObjectURL(url)

      message.success('SVG文件导出成功！')
    } catch (error) {
      console.error('Export SVG error:', error)
      message.error('SVG导出失败，请重试')
    }
  }

// 导出PNG - 使用HTML2Canvas避免Canvas污染
  const exportPNG = async () => {
    if (!mm || !svgRef.value) {
      message.warning('暂无思维导图可导出')
      return
    }

    try {
      // 方法1：直接使用SVG数据URL避免Canvas污染
      const svg = svgRef.value
      const bbox = (svg as any).getBBox()
      const padding = 40
      const width = bbox.width + padding * 2
      const height = bbox.height + padding * 2

      // 克隆SVG并内联所有样式
      const svgClone = svg.cloneNode(true) as SVGElement

      // 设置SVG属性
      svgClone.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
      svgClone.setAttribute('width', width.toString())
      svgClone.setAttribute('height', height.toString())
      svgClone.setAttribute('viewBox', `${bbox.x - padding} ${bbox.y - padding} ${width} ${height}`)

      // 添加白色背景
      const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')
      rect.setAttribute('x', (bbox.x - padding).toString())
      rect.setAttribute('y', (bbox.y - padding).toString())
      rect.setAttribute('width', width.toString())
      rect.setAttribute('height', height.toString())
      rect.setAttribute('fill', '#ffffff')
      svgClone.insertBefore(rect, svgClone.firstChild)

      // 内联所有样式到SVG元素
      const allElements = svgClone.querySelectorAll('*')
      allElements.forEach((element) => {
        const computedStyle = window.getComputedStyle(element as Element)
        let styleStr = ''

        // 重要样式属性
        const importantProps = [
          'font-family',
          'font-size',
          'font-weight',
          'font-style',
          'fill',
          'stroke',
          'stroke-width',
          'opacity',
          'text-anchor',
          'dominant-baseline',
        ]

        importantProps.forEach((prop) => {
          const value = computedStyle.getPropertyValue(prop)
          if (value && value !== 'initial' && value !== 'inherit') {
            styleStr += `${prop}: ${value}; `
          }
        })

        if (styleStr) {
          ;(element as HTMLElement).setAttribute('style', styleStr)
        }
      })

      // 创建一个新的Canvas使用data URL方式
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')

      if (!ctx) {
        throw new Error('无法获取Canvas上下文')
      }

      canvas.width = width
      canvas.height = height

      // 绘制白色背景
      ctx.fillStyle = '#ffffff'
      ctx.fillRect(0, 0, width, height)

      // 将SVG转换为data URL
      const svgData = new XMLSerializer().serializeToString(svgClone)
      const svgDataUrl = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgData)}`

      // 创建Image并使用data URL
      const img = new Image()

      return new Promise<void>((resolve, reject) => {
        img.onload = () => {
          try {
            // 绘制图片到Canvas
            ctx.drawImage(img, 0, 0, width, height)

            // 使用toDataURL代替toBlob避免污染问题
            const dataUrl = canvas.toDataURL('image/png', 1.0)

            // 创建下载链接
            const a = document.createElement('a')
            a.href = dataUrl
            a.download = `mindmap-${Date.now()}.png`
            document.body.appendChild(a)
            a.click()
            document.body.removeChild(a)

            message.success('PNG文件导出成功！')
            resolve()
          } catch (error) {
            reject(error)
          }
        }

        img.onerror = () => {
          reject(new Error('图片加载失败'))
        }

        // 使用data URL避免跨域问题
        img.src = svgDataUrl
      })
    } catch (error) {
      console.error('Export PNG error:', error)
      message.error('PNG导出失败，请重试')
    }
  }

// 下载Markdown文件
  const downloadMarkdown = () => {
    if (!markdownContent.value) {
      message.warning('暂无内容可下载')
      return
    }
    const blob = new Blob([markdownContent.value], { type: 'text/markdown' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `ai-expanded-content-${Date.now()}.md`
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)

    message.success('Markdown文件下载成功')
  }

// 监听窗口大小变化
  const handleResize = () => {
    if (mm) {
      mm.fit()
    }
  }

// 组件挂载 - 参考示例实现
  onMounted(() => {
    // console.log('Component mounted, svgRef:', svgRef.value)
    nextTick(() => {
      if (svgRef.value) {
        mm = Markmap.create(svgRef.value, {
          duration: 100,
        })
        update()
      } else {
        console.error('SVG ref not found')
      }
    })
    window.addEventListener('resize', handleResize)
  })

// 组件卸载时清理
  onUnmounted(() => {
    if (mm) {
      mm.destroy()
    }
    window.removeEventListener('resize', handleResize)
  })
</script>

<style scoped>
.text-expansion-container {
  min-height: calc(100vh - 85px);

  padding: 15px;
  position: relative;
}

.text-expansion-container::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><pattern id="grain" width="100" height="100" patternUnits="userSpaceOnUse"><circle cx="50" cy="50" r="0.5" fill="%23ffffff" opacity="0.1"/></pattern></defs><rect width="100" height="100" fill="url(%23grain)"/></svg>');
  pointer-events: none;
  z-index: 0;
}

/* 输入区域样式 */
.input-section {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(15px);
  padding: 15px;
  box-shadow:
    0 20px 60px rgba(0, 0, 0, 0.15),
    0 8px 24px rgba(0, 0, 0, 0.1);
  position: relative;
  z-index: 1;
}

.input-container {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  max-width: 1200px;
  margin: 0 auto;
}

.input-label {
  flex-shrink: 0;
  font-size: 16px;
  font-weight: 600;
  color: #333;
  padding-top: 12px;
  min-width: 80px;
}

.input-wrapper {
  flex: 1;
}

.input-header {
  text-align: center;
  margin-bottom: 32px;
}

.input-header h2 {
  margin: 0 0 12px 0;
  font-size: 32px;
  font-weight: 700;
  color: #1a1a1a;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  letter-spacing: -0.5px;
}

.input-header p {
  margin: 0;
  color: #666;
  font-size: 16px;
  line-height: 1.6;
}

.text-input {
  border-radius: 12px;
  border: 2px solid rgba(102, 126, 234, 0.2);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  background: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(5px);
  font-size: 14px;
  max-height: 120px; /* 你想要的最大高度 */
  /*   overflow-y: auto; /* 超出后显示滚动条 */
  resize: vertical; /* 允许用户上下拖拽，但不会突破 max-height */
}

.text-input:focus,
.text-input:hover {
  border-color: #667eea;
  box-shadow:
    0 0 0 4px rgba(102, 126, 234, 0.15),
    0 8px 24px rgba(102, 126, 234, 0.15);
  background: rgba(255, 255, 255, 1);
}

.action-buttons {
  flex-shrink: 0;
  display: flex;
  align-items: flex-start;
  padding-top: 8px;
}

.send-button {
  height: 48px;
  padding: 0 24px;
  border-radius: 12px;
  font-weight: 600;
  font-size: 16px;
  display: flex;
  align-items: center;
  gap: 8px;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border: none;
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

.send-button:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
}

.action-buttons .ant-btn-primary {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border: none;
  box-shadow:
    0 8px 24px rgba(102, 126, 234, 0.4),
    0 4px 8px rgba(0, 0, 0, 0.1);
  position: relative;
  overflow: hidden;
}

.action-buttons .ant-btn-primary::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.3), transparent);
  transition: left 0.6s;
}

.action-buttons .ant-btn-primary:hover::before {
  left: 100%;
}

.action-buttons .ant-btn-primary:hover {
  transform: translateY(-3px);
  box-shadow:
    0 12px 32px rgba(102, 126, 234, 0.5),
    0 6px 12px rgba(0, 0, 0, 0.15);
}

/* 内容区域样式 */
.content-section {
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(15px);
  overflow: hidden;
  position: relative;
  z-index: 1;
}

.content-layout {
  display: flex;
  height: calc(100vh - 300px);
  min-height: 700px;
}

/* 面板样式 */
.markdown-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  border-right: 1px solid rgba(232, 234, 237, 0.6);
  min-width: 0;
}

.mindmap-panel {
  flex: 4;
  display: flex;
  flex-direction: column;
  border-right: none;
  min-width: 0;
}

.panel-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 24px 28px;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.05) 100%);
  border-bottom: 1px solid rgba(232, 234, 237, 0.6);
  backdrop-filter: blur(5px);
}

.panel-header h3 {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  color: #1a1a1a;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: -0.3px;
}

.panel-actions {
  display: flex;
  gap: 8px;
}

.panel-actions .ant-btn {
  border: none;
  background: rgba(255, 255, 255, 0.9);
  color: #666;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 10px;
  backdrop-filter: blur(5px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.panel-actions .ant-btn:hover {
  color: #667eea;
  background: rgba(102, 126, 234, 0.15);
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(102, 126, 234, 0.25);
}

/* Markdown编辑器样式 */
.markdown-editor-container {
  flex: 1;
  overflow: hidden;
}

.markdown-editor {
  height: 100% !important;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
}

:deep(.cm-editor) {
  height: 100% !important;
  font-size: 14px;
  line-height: 1.6;
  background: rgba(255, 255, 255, 0.8);
}

:deep(.cm-content) {
  padding: 24px !important;
}

:deep(.cm-focused) {
  outline: none !important;
}

:deep(.cm-editor.cm-focused) {
  outline: none !important;
}

/* 思维导图包装器 */
.mindmap-wrapper {
  flex: 1;
  position: relative;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.02) 0%, rgba(118, 75, 162, 0.02) 100%);
  overflow: hidden;
  border-radius: 0 0 24px 0;
}

/* 思维导图SVG容器 */
.mindmap-container {
  width: 100%;
  height: 100%;
  min-height: 400px;
  border-radius: 12px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.9) 0%, rgba(248, 250, 252, 0.9) 100%);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(102, 126, 234, 0.1);
}

/* Markmap 样式覆盖 */
:deep(.markmap-node) {
  cursor: pointer;
}

:deep(.markmap-node-circle) {
  fill: #667eea;
  stroke: #764ba2;
  stroke-width: 2;
  transition: all 0.3s ease;
}

:deep(.markmap-node-circle:hover) {
  fill: #764ba2;
  stroke: #667eea;
  stroke-width: 3;
  filter: drop-shadow(0 4px 8px rgba(102, 126, 234, 0.3));
}

:deep(.markmap-node-text) {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-weight: 500;
  fill: #333;
}

:deep(.markmap-link) {
  stroke: #91d5ff;
  stroke-width: 2;
  opacity: 0.8;
  transition: all 0.3s ease;
}

:deep(.markmap-link:hover) {
  stroke: #667eea;
  stroke-width: 3;
  opacity: 1;
}

/* 思维导图控制提示 */
.mindmap-controls {
  position: absolute;
  bottom: 20px;
  left: 20px;
  z-index: 10;
  pointer-events: none;
}

.control-tips {
  background: rgba(102, 126, 234, 0.9);
  color: white;
  padding: 12px 16px;
  border-radius: 12px;
  font-size: 13px;
  font-weight: 500;
  backdrop-filter: blur(10px);
  box-shadow:
    0 4px 12px rgba(102, 126, 234, 0.3),
    0 2px 4px rgba(0, 0, 0, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.control-tips span {
  display: flex;
  align-items: center;
  gap: 6px;
  letter-spacing: 0.3px;
}

/* !* 空状态样式 *! */
.empty-state {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 400px;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(15px);
  border-radius: 24px;
  box-shadow:
    0 20px 60px rgba(0, 0, 0, 0.15),
    0 8px 24px rgba(0, 0, 0, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.3);
  position: relative;
  z-index: 1;
}

/* 响应式设计 */
@media (max-width: 1200px) {
  .content-layout {
    flex-direction: column;
    height: auto;
  }

  .markdown-panel,
  .mindmap-panel {
    height: 400px;
    border-right: none;
    border-bottom: 1px solid rgba(232, 234, 237, 0.6);
  }

  .mindmap-panel {
    border-bottom: none;
  }
}

@media (max-width: 768px) {
  .text-expansion-container {
    padding: 16px;
  }

  .input-section {
    padding: 24px 20px;
    border-radius: 20px;
  }

  .input-container {
    flex-direction: column;
    gap: 16px;
  }

  .input-label {
    min-width: auto;
    padding-top: 0;
    font-size: 14px;
  }

  .action-buttons {
    padding-top: 0;
    justify-content: center;
  }

  .send-button {
    width: 100%;
    height: 44px;
  }

  .action-buttons .ant-btn {
    width: 100%;
    max-width: 200px;
  }

  .content-layout {
    height: auto;
  }

  .markdown-panel,
  .mindmap-panel {
    height: 350px;
  }

  .panel-header {
    padding: 16px 20px;
  }

  .panel-header h3 {
    font-size: 16px;
  }
}

/* 动画效果 */
.text-expansion-container * {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* 滚动条样式 */
.markdown-editor-container::-webkit-scrollbar,
.mindmap-container::-webkit-scrollbar {
  width: 8px;
}

.markdown-editor-container::-webkit-scrollbar-track,
.mindmap-container::-webkit-scrollbar-track {
  background: rgba(246, 248, 250, 0.8);
  border-radius: 4px;
}

.markdown-editor-container::-webkit-scrollbar-thumb,
.mindmap-container::-webkit-scrollbar-thumb {
  background: rgba(102, 126, 234, 0.3);
  border-radius: 4px;
}

.markdown-editor-container::-webkit-scrollbar-thumb:hover,
.mindmap-container::-webkit-scrollbar-thumb:hover {
  background: rgba(102, 126, 234, 0.5);
}
</style>
